#include <string.h>
#include <iostream>
using std::cout;
using std::ostream;
using std::endl;
//自赋值的必要性以及std::move()
class String{
public:
    String()
    :_pstr(new char[1]())
    {

    }
    String(const char * pstr)
    :_pstr(new char[strlen(pstr) + 1]())
    {
        strcpy(_pstr, pstr);
    }
    //拷贝构造函数
    String(const String & rhs)
    :_pstr(new char[strlen(rhs._pstr) + 1]())
    {
        cout << "String(const String &)" << endl;
        strcpy(_pstr, rhs._pstr);
    }
    //移动构造函数
    // String s = String("hello");
    // 写的移动构造不能够对左值的对象产生任何影响
    String(String && rhs)
    :_pstr(rhs._pstr)
    {
        cout << "String(&&)" << endl;
        //1.左操作数的指针去指向右值申请的堆空间
        //2.让右值的指针断开和堆空间的联系
        rhs._pstr = nullptr;
    }

    //赋值运算符函数
    String & operator=(const String & rhs){
        cout << "operator=(const String &)" << endl;
        if(this != &rhs){
            delete [] _pstr;
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }
    //移动赋值运算符函数
    //没有进行自赋值的判断
    String & operator=(String && rhs){
        cout << "operator=(&&)" << endl;
        //回收左操作数空间
        delete [] _pstr;
        //浅拷贝
        _pstr = rhs._pstr;
        rhs._pstr = nullptr;
        return *this;
    } 

    ~String(){
        if(_pstr){
            delete [] _pstr;
            _pstr = nullptr;
        }
    }
    friend ostream & operator<<(ostream & os, const String & rhs);

private:
    char * _pstr;
};
ostream & operator<<(ostream & os, const String & rhs){
    if(rhs._pstr){
        os << rhs._pstr;
    }
    return os;
}
void test(){
    String s("hello");
    s = String("world");
    cout << s << endl;
    //===========================
    //这个操作会调用赋值运算符函数
    s = s;
    //下面这个操作会调用什么呢？？移动赋值运算符函数
    s = std::move(s);
    cout << s << endl;
}
//在没有学习今天的课程之前，如果是下面的两个func函数
//那么都会使用拷贝构造函数来去进行一份拷贝
//并不是说之前的结论是错误的，只是因为之前没有学习移动
//构造函数，所以对于上述的处理全部都是使用拷贝构造函数来
//处理

String globalStr("global");
String func(){
    return globalStr;
}

String func2(){
    String localStr("local");
    return localStr;
}

void test2(){
    func();
    cout << "==================" << endl;
    func2();
}

int main()
{
    test2();
    return 0;
}

